package model.minimax;

import java.util.ArrayList;
import java.util.Set;

import model.GamePiece;
import model.LadderGameHelper;
import model.LadderGridHelper;
import model.Slot;

/**
 * This class build the tree with the depth of 2.
 * The depth 2 gives the best response time for our game as compared to other higher depths. 
 *
 */
public class StatesTree
{
    private StateNode root;

    public StatesTree()
    {

    }

    /**
     * Creates the children of the tree up to the specified Depth.
     * 
     * @param maxDepth
     */
    public void build(int maxDepth)
    {
        this.root.resetHeuristicValue();
        this.build(maxDepth, 0, this.root);
    }

    public void build(int maxDepth, int currentDepth, StateNode currentNode)
    {
        if (currentDepth < maxDepth)
        {
            Set<Slot> freePositions = this.root.getNextTurnPiece() == currentNode.getNextTurnPiece() ? 
                    LadderGridHelper.getAllFreePositionsAdjacentToOccupiedSlot(currentNode.getGrid()) 
                    : LadderGridHelper.getAllFreePositions(currentNode.getGrid());

            for (Slot freePosition : freePositions)
            {
                currentNode.addChild(freePosition);
            }

            // Recursive call on currentNode's children.
            for (MoveEdge edge : currentNode.getMoves())
            {
                this.build(maxDepth, currentDepth + 1, edge.getTargetNode());
            }
        }
    }

    /**
     * Returns the edge from the root whose targetNode has the max heuristic
     * value, null if the root does not have any children.
     * 
     * @return
     */
    public MoveEdge getMaxMove()
    {
        return this.root.getMaxMove();
    }

    /**
     * Returns the edge from the root whose targetNode has the min heuristic
     * value, null if the root does not have any children.
     * 
     * @return
     */
    public MoveEdge getMinMove()
    {
        return this.root.getMinMove();
    }

    public StateNode getRoot()
    {
        return root;
    }

    public void setRoot(StateNode root)
    {
//        if (this.root != null)
//        {
//            for (MoveEdge move : this.root.getMoves())
//            {
//                if (root != move.getTargetNode())
//                {
//                    move.setTargetNode(null);
//                }
//            }
//        }

        this.root = root;
    }

}
